did:ethrを作成してUniversal Resolverで呼び出す
やっている事
didDocument.jsonを作成してテストネットに保存しようとしている
code:didDocument.json
{
"ethereumAddress": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"didDocument": {
"id": "did:ethr:sepolia:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"verificationMethod": [
{
"id": "did:ethr:sepolia:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266#controller",
"type": "EcdsaSecp256k1RecoveryMethod2020",
"controller": "did:ethr:sepolia:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"blockchainAccountId": "sepolia:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
}
],
"authentication": [
"did:ethr:sepolia:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266#controller"
],
"assertionMethod": [
"did:ethr:sepolia:0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266#controller"
]
}
}
ethereumAddressがある理由はdidDocumentを保存する際にidentityが必要で、今回はEOAをidentityとするためにある
リクエストとしてdidDocumentとidentityが必要
で、ガス代とかもろもろ設定しているファイル
code:didServer.js
const Web3 = require('web3').default;
const config = require('../config');
const web3 = new Web3(Web3.givenProvider || '');
web3.eth.accounts.wallet.add('');
const ethrDidRegistry = new web3.eth.Contract(
config.ethrDidRegistryABI,
config.ethrDidRegistryAddress
);
//DID Documentをバイト列に変換
function encodeDIDDocument(didDocument) {
return '0x' + Buffer.from(JSON.stringify(didDocument)).toString('hex');
}
//DID Documentをチェーン上に保存
async function saveDIDDocument(identity, didDocument) {
if (!identity) {
throw new Error("Identity is undefined or null");
}
if (!didDocument || typeof didDocument !== 'object') {
throw new Error("DID Document is undefined, null, or not an object");
}
try {
const fromAddress = web3.eth.accounts.wallet0.address; // 送信者アドレス const didDocumentBytes = encodeDIDDocument(didDocument);
const name = 'didDocument';
const nameHex = web3.utils.asciiToHex(name);
const nameBytes32 = nameHex.padEnd(66, '0');
//console.log('nameBytes32:', nameBytes32);
const validity = 86400; // 有効期限(秒単位)
//トランザクションデータの作成
const transactionData = ethrDidRegistry.methods.setAttribute(identity, nameBytes32, didDocumentBytes, validity).encodeABI();
//トランザクションの設定
const transaction = {
from: fromAddress,
to: config.ethrDidRegistryAddress,
data: transactionData,
gas: estimatedGas
};
//トランザクションの署名
const signedTransaction = await web3.eth.accounts.signTransaction(transaction, '');
// トランザクションの送信
const transactionReceipt = await web3.eth.sendSignedTransaction(signedTransaction.rawTransaction);
console.log('Transaction Hash:', transactionReceipt.transactionHash);
return transactionReceipt;
} catch (error) {
console.error('Error in save DIDDocument:', error);
throw error; // エラーを再スローする
}
}
// ガス量の推定
const estimatedGas = await ethrDidRegistry.methods.setAttribute(identity, nameBytes32, didDocumentBytes, validity)
.estimateGas({ from: fromAddress });
console.log('Estimated Gas:' , estimatedGas);
// トランザクションの送信
console.log('setAttribute arguments:', { identity, nameBytes32, didDocumentBytes, validity });
const transactionResult = await ethrDidRegistry.methods.setAttribute(identity, nameBytes32, didDocumentBytes, validity)
.send({from: fromAddress, gas: estimatedGas });
console.log('Transaction Hash:', transactionResult.transactionHash);
console.log('Transaction Result:', transactionResult);
return transactionResult;
} catch (error) {
console.error('Error in save DIDDocument:', error);
throw error; // エラーを再スローする
}
}
//ethrDidRegistryに属性を追加する際に必要
async function setAttribute(identity, name, value, validity) {
const fromAddress = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266';
const gasLimit = 0.00004;
// nameをbytes32形式に変換
const nameBytes32 = web3.utils.padRight(web3.utils.asciiToHex(name), 66);
return ethrDidRegistry.methods.setAttribute(identity, nameBytes32, value, validity)
.send({ from: fromAddress, gas: gasLimit});
}
const createDID = (walletAddress) => {
const network = 'goerli'; // または他のネットワーク名
const did = did:ethr:${network}:${walletAddress};
const didDocument = {
'id': did,
'verificationMethod': [
{
'id': ${did}#controller,
'type': 'EcdsaSecp256k1RecoveryMethod2020',
'controller': did,
'blockchainAccountId': ${network}:${walletAddress}
}
],
'authentication': [${did}#controller],
'assertionMethod': [${did}#controller]
};
return { did, didDocument };
};
module.exports = {
createDID,
saveDIDDocument
};
空の部分は秘密鍵が入っている
これよくよく見るととテストネットが2つ混在しちゃってるわYudai.icon
JSONをgoerliに直さないといけない
で、今詰まっているところ
curl -X POST http://localhost:3000/save-did -H "Content-Type: application/json" -d @./data/didDocument.jsonが一生できないYudai.icon
bytes32じゃないといけないけどなっていなかった
この部分は直せた
出力させた0x646964446f63756d656e74000000000000000000000000000000000000000000
ちなみにエラーが出ているのに一生ガス代を払っていたんだけどYudai.icon*2
それでもトランザクションの実行が出来ていない
そのあとにchatGPT.iconからアカウント情報を載せるってことで署名の作成も含めたコードを足した
node app.jsが実行できなくなった...Yudai.icon
プライベートキーが使えていないっぽいんやけど
ええええ0xを足したら動いた
バージョンによって異なるらしい
できた!!!!
実行コマンド: curl -X POST http://localhost:3000/save-did -H "Content-Type: application/json" -d "@data/didDocument.json"
Estimated Gas: 66205nGas Price: 10n Transaction Hash: 0x06baa4fcc90acd886efbbc62d85f91dd97547201dcee5559e728ee714469d098
以前の実装だとjsonの読み取りの実装が出来ていなかったっぽい
だから別ファイルに実装した
code:loadAndSaveDID.js
const fs = require('fs');
const didService = require('./src/services/didService');
fs.readFile('path/to/didDocument.json', 'utf8', async (err, data) => {
if (err) {
console.error('Error reading the file:', err);
return;
}
try {
const jsonData = JSON.parse(data);
const result = await didService.saveDIDDocument(jsonData.ethereumAddress, jsonData.didDocument);
console.log('DID Document saved:', result);
} catch (error) {
console.error('Error processing the data:', error);
}
});
このfsによって出来ているっぽいYudai.icon
あと全然できなかったところはガス代
僕の方で指定していたのが足りなさ過ぎたっぽくて、自動的に計算?出来るようにしたのとweiだと単位的に足りなくて、gweiにしたらいけたYudai.icon
最終目標
did:ethrでdid documentの作成と保存 -> Universal Resolverで呼び出し -> 署名検証 -> JSONファイルをconnect walletからowner addressを取り出して作成 上記ができればdidと空間を繋ぐことができる